#include <cmath>
#include "Image.h"
#include "waveletTransform.h"
#include "binFile.h"
#include <iostream>
#include <iterator>
#include "compressData.h"
#include "compress.h"
#include "decompress.h"
#include <cstdlib>
#include <string>




int main(int argc, char *argv[])
{


    Compress *test1;
    Decompress *test2;

    std::string file(argv[1]);

    if(atoi(argv[2])==1)
    {
        test1=new Compress(new WaveletTransform(new NewHarr(512)),atoi(argv[3]));
      //  test2=new Decompress(new WaveletTransform(new NewHarr(512)),atoi(argv[3]));
    }
    else if(atoi(argv[2])==2)
    {
        test1=new Compress(new WaveletTransform(new LeGall(512,false)),atoi(argv[3]));
        //test2=new Decompress(new WaveletTransform(new LeGall(512,true)),atoi(argv[3]));
    }

    Image *image=new Image(file);

    image->rgbToYCbCr();

    DecompressData *aaa=test1->startCompress(image,atoi(argv[2]));


    //////////////////////////////////////
    std::map<int,double> frequency;
    std::map<int,double> ::iterator it;





    for(int i=-14000; i<14000 ;++i)
    {
        if(std::abs(i)>100)
        {
            frequency[i]=1;
        }
        if(std::abs(i)>50&&std::abs(i)<=100)
        {
            frequency[i]=5;
        }
        if(std::abs(i)>30&&std::abs(i)<=50)
        {
            frequency[i]=15;
        }
        if(std::abs(i)>30&&std::abs(i)<=50)
        {
            frequency[i]=15;
        }
        if(std::abs(i)>4&&std::abs(i)<=30)
        {
            frequency[i]=50;
        }

    }


 //   frequency[10000]=43929;
    frequency[0]=740889;
    frequency[-1]=11409;
    frequency[1]= 11964;
    frequency[-4]= 1189;
    frequency[-3]=2017;
    frequency[-2]= 4055;
    frequency[2]= 4293;
    frequency[3]= 2089;
    frequency[4]= 1266;


    for(it=frequency.begin(); it!=frequency.end();++it)
    {
        //std::cout<<(*it).first<<" "<<(*it).second<<std::endl;
        double tmp=(*it).second/(512*512);
        frequency[(*it).first]=tmp;
    }

  //  std::cout<<"Fsize "<<frequency.size()<<std::endl;

    Hufftree<int, double> hufftree(frequency.begin(), frequency.end());

    //////////////////////////////////////////////////////////////////




    std::vector<uint32_t> data;
    std::vector<bool> bdata;
    loadBits("compress.bin",&data);




    for(unsigned int j=0; j<data.size(); ++j)
    {

        for(int i=31; i>=1; i--)
        {

            if ((data[j] & ( 1 << i)) > 0 )
            {
                bdata.push_back(1);
            }
            else if(( data[j] & ( 1 << i) ) == 0)
            {
                bdata.push_back(0);
            }

        }
    }



    std::vector<double> destination;
    hufftree.decode(bdata, std::back_inserter(destination));




    double** Y=new double* [512];
    double** Cb=new double* [512];
    double** Cr=new double* [512];


    for(int i=0; i<512; ++i)
    {
        Y[i]=new double [512];
        Cr[i]=new double [512];
        Cb[i]=new double [512];
    }




    int k=0;
    int l=0;
    int rle=64;




    int wave=destination[0];
    ++l;

    for(int i=0; i<512; ++i)
    {
        for(int j=0; j<512; ++j)
        {

            Y[i][j]=destination[l];
                    ++l;
         }

    }

    for(int i=0; i<512; ++i)
    {
        for(int j=0; j<512; ++j)
        {

            Cb[i][j]=destination[l];
                    ++l;
         }

    }
    for(int i=0; i<512; ++i)
    {
        for(int j=0; j<512; ++j)
        {

            Cr[i][j]=destination[l];
                    ++l;
         }

    }

    DecompressData *ccc=new DecompressData(512,512);

    ccc->setY(Y);
    ccc->setCb(Cb);
    ccc->setCr(Cr);


/*
    for(int i=0; i<destination.size();++i)
    {

        if(destination[i]==10000)
        {
            for(int m=1; m<=rle;++m)
            {
                Y[k][l]=0
                ++l;

                if(l>=512)
                {
                    ++k;
                    l=0;
                }

            }
            continue;
        }


        if(k>=512)
        {
            std::cout<<"koniec"<<std::endl;
            break;
        }
             Y[k][l]=destination[i];
            ++l;
        if(l>=512)
        {
                 ++k;
                 l=0;
        }

    }

    */

   // exit(0);

    Image* imag2=new Image(aaa->getY(), aaa->getCb(), aaa->getCr(), 512, 512);

    imag2->YCbCrToRgb(512,512);
    imag2->saveImage("test1.png");








    if(wave==1)
    {
      //  test1=new Compress(new WaveletTransform(new NewHarr(512)),atoi(argv[3]));
        test2=new Decompress(new WaveletTransform(new NewHarr(512)),atoi(argv[3]));
    }
    else if(wave==2)
    {
        //test1=new Compress(new WaveletTransform(new LeGall(512,false)),atoi(argv[3]));
        test2=new Decompress(new WaveletTransform(new LeGall(512,true)),atoi(argv[3]));
    }



    DecompressData *BBB=test2->startDecompress(ccc,image->getWidth(),image->getHeight());

    std::cout<<"1"<<std::endl;

    Image* imag3=new Image(BBB->getY(), BBB->getCb(), BBB->getCr(), 512, 512);

    imag3->YCbCrToRgb(512,512);
    imag3->saveImage("test.png");


    std::cout<<"2"<<std::endl;



    // delete aaa;
    // delete BBB;

    // delete image;
    // delete test1;
    // delete test2;
    // delete imag2;

    return 0;
}
